#include "mod_4g.h"

#include "usart.h"
#include "platform.h"
#include "port.h"
#include "data.h"

#include <stdlib.h>
#include <string.h>
#include <ctype.h>

struct T_NetW4g {
    uint8_t serveip[4];  //远程服务器IP地址
    uint32_t serveport;  //远程服务器端口号
    int reLinkCnt; //记录上电后网络重连次数
    uint8_t linkstate;
    uint8_t csq;  //信号强度
    uint8_t tcp_socket;
    uint8_t ftp_socket;
};

enum {GPRS_SUCCESS = 0, GPRS_ERR = -1};

#define GPRS_SEND_BUF_CNT 3
#define GPRS_SEND_BUF_LEN_MAX 512
#define GPRS_RECV_BUF_LEN_MAX 1500
#define GPRS_RECV_ACK_BUF_LEN 1500
#define GPRS_RECV_DATA_LEN 2048

#define FTP_FILE_PACK_LEN 500   //FTP每包数据大小
#define FTP_FAIL_CNT_MAX 10      //下载或上传文件失败重试次数


struct FtpInfo{
    uint8_t cmd;         //ftp命令码，下载文件或上传文件等
    ftp_cb_func func;    //ftp运行中的回调函数，返回ftp执行成功或失败
    uint8_t state;       //为1时表示启动ftp上传或下载动作
    int32_t file_len;    //文件总长度
    int32_t file_offset; //文件偏移
    int32_t pack_len;    //当前包长度
    int32_t fail_cnt;    //文件处理失败计数
    uint8_t need_relink; //网络中断过，需要重连
    
    char_t ip[30];       //ftp ip
    int32_t port;
    char_t user[30];
    char_t pwd[30];
    char_t path[50];     //文件路径   
};

struct W4gTcpHead {
    uint8_t socket;
    uint8_t ip[4];
    int32_t port;
    int32_t len;
};

static struct FtpInfo g_ftpInfo = {0};

static struct T_NetW4g g_w4g = {0};
static char_t g_recv_ack_buf[GPRS_RECV_ACK_BUF_LEN] = {0};
static int32_t g_recv_ack_buf_len = 0;
static os_mutex_t g_w4g_mutex = NULL;

static void w4g_recv_set_ack_chr(char_t chr){
    if (g_recv_ack_buf_len + 1 < GPRS_RECV_ACK_BUF_LEN){
        g_recv_ack_buf[g_recv_ack_buf_len] = chr;
        g_recv_ack_buf_len += 1;
    }
}
static void W4g_Recv_SetAckData(const char *buf, int len) {
    if (g_recv_ack_buf_len + len < GPRS_RECV_ACK_BUF_LEN){
        memcpy(&g_recv_ack_buf[g_recv_ack_buf_len], buf, len);
        g_recv_ack_buf_len += len;
    }
}

static int W4g_Recv_GetAckData(char *buf, int len) {
    int32_t read_len = (len < g_recv_ack_buf_len)? len:g_recv_ack_buf_len;
    memcpy(buf, g_recv_ack_buf, read_len);
    return read_len;
}

static void W4g_Recv_ClearAckData() {
    memset(g_recv_ack_buf, 0, sizeof(g_recv_ack_buf));
    g_recv_ack_buf_len = 0;
}

//w4g 接收解析
struct T_W4gRecv {
    uint32_t len;
    char buf[GPRS_RECV_BUF_LEN_MAX];
};

static xQueueHandle w4g_recv_queue = NULL;

void print_chr(char_t chr){
    if(isprint(chr)){
        printf("%c", chr);
    }else{
        printf("{%02x}", chr);
    }
}

void print_str(const char_t *str, int32_t len){
    for(int32_t i=0;i<len;i++){
        print_chr(str[i]);
    }
    printf("\r\n");
}


int32_t w4g_set_msg(char_t *buf, uint32_t len){
    for(uint32_t i=0;i<len;i++){
          xQueueSend(w4g_recv_queue, &buf[i], portTICK_PERIOD_MS);
    }
    return 0;
}

static void W4gRecv_Clear(struct T_W4gRecv *gr) {
    memset(gr->buf, 0, GPRS_RECV_BUF_LEN_MAX);
    gr->len = 0;
}

static void W4gRecv_Push(struct T_W4gRecv *gr, uint8_t val) {
    if (gr->len >= GPRS_RECV_BUF_LEN_MAX) {
        printf("W4gRecv_Push len >= GPRS_RECV_BUF_LEN_MAX\r\n");
        W4gRecv_Clear(gr);
    }
    gr->buf[gr->len++] = (char)val;
}

static int32_t W4gRecv_IsValidAck(const struct T_W4gRecv *gr) {
    return (gr->len > 2);
}

static int32_t GetTcpHead(const char *p, int32_t len, struct W4gTcpHead *head){
    int32_t socket=0;
    int32_t ip1=0;
    int32_t ip2=0;
    int32_t ip3=0;
    int32_t ip4=0;
    int32_t port = 0;
    int32_t data_len = 0;
    char_t *begin = strstr(p, "+ZIPRECV:");
    
    if (sscanf(begin, "+ZIPRECV: %d,%d.%d.%d.%d,%d,%d,", &socket, &ip1, &ip2, &ip3, &ip4, &port, &data_len) == 7){
        head->socket = socket;
        head->ip[0] = ip1;
        head->ip[1] = ip2;
        head->ip[2] = ip3;
        head->ip[3] = ip4;
        head->port = port;
        head->len = data_len;
        return 0;
    }
    return -1;
}

//如果收到数据包，则返回数据起始位置
static uint32_t is_recv_data(struct T_W4gRecv *gr){
    char *p=NULL;
    char *q=NULL;
    p = strstr(gr->buf, "+ZIPRECV:");
    if (p == NULL){
        return 0;
    }
    q = p;
    for(int32_t i=0; i<4;i++){
        q = strchr(q+1, ',');
        if (q == NULL){
            return 0;
        }
        if (gr->len <= (q - gr->buf)){
            return 0;
        }
    }
    return q+1 - gr->buf;
}


struct T_IpdInfo {
    struct W4gTcpHead head;
    char *pos;
};

static int32_t GetIPDData(struct T_W4gRecv *gr, struct T_IpdInfo *info) {
    int32_t ret = GetTcpHead(gr->buf, gr->len, &info->head);
    if (ret == 0){
        uint32_t pos = is_recv_data(gr);
        if (pos != 0) {            
            info->pos = &gr->buf[pos];
            return 0;
        }
    }

    return -1;
}

static struct T_W4gRecv g_w4gRcv = {0};


//中断调用函数
void W4gRecv_Parse(uint8_t val) {
    print_chr(val);

    W4gRecv_Push(&g_w4gRcv, val);
    if ((g_w4gRcv.len > 2) && (g_w4gRcv.buf[g_w4gRcv.len-2] == '\r') && (g_w4gRcv.buf[g_w4gRcv.len-1] == '\n')) {
        struct T_IpdInfo info={0};
        int32_t ret = GetIPDData(&g_w4gRcv, &info);
        if(ret == 0) {            //说明有一条完整的IPD数据
            w4g_set_msg(info.pos, info.head.len);        
        } else {                       //说明没有IPD数据
            W4g_Recv_SetAckData(g_w4gRcv.buf, (int)g_w4gRcv.len);
            //print_str(g_recv_ack_buf, strlen(g_recv_ack_buf));
        }
        //print_str(g_w4gRcv.buf, g_w4gRcv.len);
        W4gRecv_Clear(&g_w4gRcv);
    }

}

static void NetW4g_power_on() {
    w4g_power_low();
    os_msleep(200);
    w4g_power_high();
    os_msleep(1000);
}

static void NetW4g_Reset() {
    w4g_reset_low();
    os_msleep(200);
    w4g_reset_high();
    os_msleep(5000);
}


static int NetW4g_Write(const char *cmd, uint32_t len) {
    print_str(cmd, len);
    //printf("-->len:%d %s\r\n",len,cmd);
    usart3_send((uint8_t *)cmd, len);
    return 0;
}

int32_t FindW4gMsg(const char *msg) {
    if (g_recv_ack_buf_len == 0){
        return 0;
    }
    return (strstr(g_recv_ack_buf, msg) == NULL) ? 0 : 1;
}

static int NetW4g_GetAck(const char *ack, int msec) {
    int recCnt = msec / 20;
    uint32_t cnt = 0;
    while(recCnt) {
        os_msleep(20);
        
        cnt++;
        
        recCnt--;

        int32_t i = FindW4gMsg((char *)"ERROR\r\n");
        if(i) { //如果error在里面
            return GPRS_ERR;
        }
        i = FindW4gMsg((char *)ack);
        if(i) {
            return GPRS_SUCCESS;

        }
    }
    return GPRS_ERR;
}

static int NetW4g_SendCmd(const char *cmd, const char *ack, int msec, int cnt) {
    //printf("SendCmd %s",cmd);
    os_mutex_lock(&g_w4g_mutex);
    for (uint8_t i = 0; i < cnt; i++) {
        W4g_Recv_ClearAckData();
        NetW4g_Write(cmd, strlen(cmd));
        if (msec == 0) {
            os_mutex_unlock(&g_w4g_mutex);
            return GPRS_SUCCESS;
        }
        if (NetW4g_GetAck(ack, msec) == GPRS_SUCCESS) {
            os_mutex_unlock(&g_w4g_mutex);
            return GPRS_SUCCESS;
        }
    }
    os_mutex_unlock(&g_w4g_mutex);
    return GPRS_ERR;
}

static int32_t get_csq_value(){
    int32_t csq = 0;
    char_t *begin = strstr(g_recv_ack_buf, "+CSQ:");
    sscanf(begin, "+CSQ: %d,", &csq);
    printf("csq:%d\r\n", csq);
    return csq;
}

void static get_csq(struct T_NetW4g *ng){
    char_t *cmd = "AT+CSQ\r";
    os_mutex_lock(&g_w4g_mutex);
    W4g_Recv_ClearAckData();
    NetW4g_Write(cmd, strlen(cmd));
    if (NetW4g_GetAck("+CSQ:", 200) == GPRS_SUCCESS) {
        ng->csq = get_csq_value();
    }
    os_mutex_unlock(&g_w4g_mutex);
}

static int32_t NetW4g_CheckGprsLink(void) {
    
    get_csq(&g_w4g);
    
    if (NetW4g_SendCmd("AT+ZIPSTAT=1\r", "+ZIPSTAT: 1,1\r\n", 1000, 2) == GPRS_SUCCESS) {
        printf("NetW4g_CheckGprsLink link ok\r\n");
        return 1;
    }
    printf("NetW4g_CheckGprsLink unlink\r\n");
    return 0;
}

static int NetW4g_SendATCIPSTART(int32_t socket, uint8_t *ip, int32_t port) {
    char buf[100] = {0};
    sprintf(buf, "AT+ZIPOPEN=%d,0,%d.%d.%d.%d,%d\r", socket, ip[0], ip[1], ip[2], ip[3], port);
    os_mutex_lock(&g_w4g_mutex);
    W4g_Recv_ClearAckData();
    NetW4g_Write(buf, strlen(buf));
    for(uint32_t i = 0; i < 75; i++) {
        
        os_msleep(1000);//延时1秒钟
        if (FindW4gMsg((char *)"OK\r\n")) {
            os_mutex_unlock(&g_w4g_mutex);
            return 1;
        }
        if(FindW4gMsg((char *)"CONNECT FAIL\r\n")) {
            os_mutex_unlock(&g_w4g_mutex);
            return 0;
        }
    }
    os_mutex_unlock(&g_w4g_mutex);
    return 0;
}

void NetW4g_SetGPRSLink(struct T_NetW4g *ng, int32_t state) {
    g_w4g.linkstate = state;
}

/*lint -e{801} */
static int NetW4g_Connect(struct T_NetW4g *ng) {
    printf("w4g connect......reLinkCnt:%d\r\n", ng->reLinkCnt);
    os_msleep(3000);

    NetW4g_SendCmd("ATE0\r", "", 200, 1); //关闭回显 发送 ATE0\n

    if (NetW4g_SendCmd("AT+CPIN?\r", "+CPIN: READY\r\n", 2000, 5) != GPRS_SUCCESS) { //发送 AT+CPIN?\n 应答 +CPIN: READY
        printf("NetW4g_SendCmd AT+CPIN? err\r\n");
        goto OVER;
    }
    os_msleep(2000);
    get_csq(ng);

    if (NetW4g_SendCmd("AT+CEREG?\r", "+CEREG: 0,1\r\n", 2000, 15) != GPRS_SUCCESS) { //查询当前w4g附着状态  发送 AT+CGATT?\n 应答 +CGATT: 1
        printf("NetW4g_SendCmd AT+CEREG? err\r\n");
        goto OVER;
    }

    if (NetW4g_SendCmd("AT+ZIPCFG=ctnet,user,1234\r", "OK\r\n", 2000, 2) != GPRS_SUCCESS) { //IP CALL 初始化
        printf("NetW4g_SendCmd AT+ZIPCFG err\r\n");
        goto OVER;
    }

    if (NetW4g_SendCmd("AT+ZIPCALL=1\r", "+ZIPCALL:", 5000, 3) != GPRS_SUCCESS) { //打开IP CALL
        printf("NetW4g_SendCmd AT+ZIPCALL=1 err\r\n");
        goto OVER;
    }

    if(!NetW4g_SendATCIPSTART(ng->tcp_socket, ng->serveip, ng->serveport)) {
        printf("NetW4g_SendCmd ATCIPSTART err\r\n");
        goto OVER;
    }
    printf("w4g connect success\r\n");
    NetW4g_SetGPRSLink(ng, (int32_t)1);//设置状态为连接
    return 1;

OVER:
    printf("w4g connect fail\r\n");
    NetW4g_Reset();

    ng->reLinkCnt++;

    return 0;
}

static int32_t NetW4g_reconnect(struct T_NetW4g *ng){
    if (NetW4g_SendCmd("AT+ZIPCLOSE=1\r", "+ZIPSTAT: 1,0\r\n", 1000, 2) != GPRS_SUCCESS) { //关闭socket
        printf("NetW4g_reconnect send AT+CGREG? err\r\n");
        return -1;
    }
    if(!NetW4g_SendATCIPSTART(ng->tcp_socket, ng->serveip, ng->serveport)) { //连接到服务器
        printf("NetW4g_reconnect send ATCIPSTART err\r\n");
        return -1;
    }
    printf("w4g re connect success\r\n");
    NetW4g_SetGPRSLink(ng, (int32_t)1);//设置状态为连接
    return 0;
}

static void NetW4g_init(struct T_NetW4g *ng) {
    
    os_msleep(500);//强制等待500毫秒;
    NetW4g_Connect(ng); //说明发起连接成功
}

int32_t NetW4g_IsGrpsConnect(void) {
    return g_w4g.linkstate;
}

int32_t w4g_connect(void) {
    if (g_w4g.linkstate){
        if (NetW4g_CheckGprsLink() == 0) { //socket 状态为断开
            g_w4g.linkstate = 0;
            NetW4g_init(&g_w4g);
        }else{    //socket 状态为连接
            NetW4g_reconnect(&g_w4g);
        }
    }else{
        NetW4g_init(&g_w4g);
    }
    if (g_w4g.linkstate){
        return 0;
    }
    return -1;
}

int32_t w4g_tcp_send_msg(const char *buf, uint32_t buflen, uint8_t socket) {
    if (buflen >= GPRS_RECV_BUF_LEN_MAX) {
        printf("w4g_send_msg len:%d > max:%d\r\n", (int)buflen, (int)GPRS_RECV_BUF_LEN_MAX);
        return -1;
    }
    if (!g_w4g.linkstate) {
        return -1;
    }
    
    char_t send_cmd[50]={0};
    sprintf(send_cmd, "AT+ZIPSENDRAW=%d,%d\r", socket, (int)buflen);
    
    os_mutex_lock(&g_w4g_mutex);
    W4g_Recv_ClearAckData();
    NetW4g_Write((const char *)send_cmd, strlen(send_cmd));
    os_msleep(50);
    
    NetW4g_Write((const char *)buf, buflen);
    NetW4g_GetAck("OK\r\n", 100);
    
    os_mutex_unlock(&g_w4g_mutex);
    
    return buflen;
}

int32_t w4g_send_msg(const char *buf, uint32_t buflen) {
    return w4g_tcp_send_msg(buf, buflen, g_w4g.tcp_socket);
}

int32_t w4g_ftp_send_msg(const char *buf, uint32_t buflen) {
    return w4g_tcp_send_msg(buf, buflen, g_w4g.ftp_socket);
}

int32_t w4g_read_msg(char_t *buf, uint32_t len){
    uint32_t i=0;
    for(i=0;i<len;i++){
        BaseType_t xResult = xQueueReceive(w4g_recv_queue, &buf[i], portTICK_PERIOD_MS);
        if (xResult != pdPASS){
            break;
        }    
    }

    return i;
}

int32_t w4g_ftp_connect_server(char_t *ip, int32_t port){
    if (!g_w4g.linkstate) {
        printf("w4g_ftp_connect_server linkstate==0\r\n");
        return -1;
    }
    if(!NetW4g_SendATCIPSTART(g_w4g.ftp_socket, g_w4g.serveip, g_w4g.serveport)) {
        printf("NetW4g_SendCmd ATCIPSTART err\r\n");
        return -1;
    }
    return 0;
}

int32_t w4g_socket_create(int32_t socket){
    if (!g_w4g.linkstate) {
        printf("w4g_socket_create linkstate==0\r\n");
        return -1;
    }
    return socket;    
}

int32_t w4g_socket_connect(uint8_t socket, uint8_t *addr, int32_t port){
    if (!g_w4g.linkstate) {
        printf("w4g_socket_connect linkstate==0\r\n");
        return -1;
    }
    if(!NetW4g_SendATCIPSTART(socket, addr, port)) {
        printf("w4g_socket_connect ATCIPSTART err\r\n");
        return -1;
    }
}

int32_t w4g_ftp_send_cmd(char_t *buf, int32_t len){

}

//AT$ZFTPCFG=219.144.130.27,test,test 
int32_t w4g_ftp_set_config(char_t *ip, int32_t port, char_t *user, char_t *pwd){
    if (!g_w4g.linkstate) {
        printf("w4g_ftp_set_config linkstate==0\r\n");
        return -1;
    }
    //strncpy(g_ftpInfo.ip, ip, sizeof(g_ftpInfo));
    //g_ftpInfo.port = port;
    //strncpy(g_ftpInfo.user, user, sizeof(g_ftpInfo.user));
    //strncpy(g_ftpInfo.pwd, pwd, sizeof(g_ftpInfo.pwd));
    
    char_t cmd[50]={0};
    sprintf(cmd, "AT$ZFTPCFG=%s:%d,%s,%s\r", ip, port, user, pwd);
    if (NetW4g_SendCmd(cmd, "OK\r\n", 10000, 1) != GPRS_SUCCESS) { 
        printf("NetW4g_SendCmd fail: %s \r\n",cmd);
        return -1;
    }
    printf("w4g_ftp_set_config success\r\n");
    return 0;
}

int32_t get_ftp_file_size(){
    int32_t size = 0;
    char_t *begin = strstr(g_recv_ack_buf, "$ZFTPSIZE:");
    sscanf(begin, "$ZFTPSIZE: %d,", &size);
    printf("ftp file size:%d\r\n", size);
    return size;
}

//AT$ZFTPSIZE=ftp1.txt 
int32_t w4g_ftp_get_file_size(char_t *path){
    char_t cmd[50]={0};
    sprintf(cmd, "AT$ZFTPSIZE=%s\r", path);
    
    os_mutex_lock(&g_w4g_mutex);
    
    W4g_Recv_ClearAckData();
    NetW4g_Write(cmd, strlen(cmd));
    if (NetW4g_GetAck("$ZFTPSIZE:", 10000) == GPRS_SUCCESS) {
        
        os_mutex_unlock(&g_w4g_mutex);
        
        return get_ftp_file_size();
    }
    
    os_mutex_unlock(&g_w4g_mutex);
    
    return -1;
}

static int w4g_get_ftp_recv_len(int msec) {
    int recCnt = msec / 10;
    while(recCnt) {
        os_msleep(10);
        recCnt--;
        if (g_recv_ack_buf[g_recv_ack_buf_len-6] == '\r' && g_recv_ack_buf[g_recv_ack_buf_len-5] == '\n'
            && g_recv_ack_buf[g_recv_ack_buf_len-4] == 'O' && g_recv_ack_buf[g_recv_ack_buf_len-3] == 'K' 
            && g_recv_ack_buf[g_recv_ack_buf_len-2] == '\r' && g_recv_ack_buf[g_recv_ack_buf_len-1] == '\n'){
            
            return g_recv_ack_buf_len-6;
        }
    }
    return -1;
}

//AT$ZFTPGET=test.txt,0,15 
int32_t w4g_ftp_get_file_data(char_t *path, int32_t offset, int32_t len, char_t *data, int32_t data_len_max){
    char_t cmd[50]={0};
    int32_t recv_len = 0;
    sprintf(cmd, "AT$ZFTPGET=%s,%d,%d\r", path, offset, len);
    
    os_mutex_lock(&g_w4g_mutex);
    
    W4g_Recv_ClearAckData();
    NetW4g_Write(cmd, strlen(cmd));
    
    recv_len = w4g_get_ftp_recv_len(10000);
    if ((recv_len > 0) && (recv_len <= data_len_max)){
        memcpy(data, g_recv_ack_buf, recv_len);
        
        os_mutex_unlock(&g_w4g_mutex);
        
        return recv_len;
    }
    
    os_mutex_unlock(&g_w4g_mutex);
    
    return -1;
}

void w4g_ftp_poll(struct FtpInfo *info){
    char_t buf[FTP_FILE_PACK_LEN+1]={0};
    if (info->state == 0){
        return;
    }
    if (!g_w4g.linkstate){
        info->need_relink = 1;
        return;
    }else{
        if (info->need_relink)  {
             //if(w4g_ftp_set_config(info->ip, info->port, info->user, info->pwd) != 0)  {
             //    return;
             //}
             info->need_relink = 0;
        }
    }
    
    info->pack_len =  ((info->file_offset +  FTP_FILE_PACK_LEN) > info->file_len) ? (info->file_len - info->file_offset) : FTP_FILE_PACK_LEN;
    int32_t len = w4g_ftp_get_file_data(info->path, info->file_offset, info->pack_len, buf, FTP_FILE_PACK_LEN);
    //printf("len:%d pack_len:%d\r\n", len, info->pack_len);
    if (len == info->pack_len){
        if (data_push_update_file_data(FLASH_UPDATE_MASTER_FILE, info->file_offset, buf, len) == 0){
            printf("load:%d/%d",info->file_offset, info->file_len);
            info->fail_cnt = 0;
            info->file_offset += len; 
            if (info->file_offset == info->file_len){
                info->func(FTP_RET_SUCCESS);
                info->state = 0;
            }
        }else{
            info->fail_cnt++;
        }
        
    }else{
        info->fail_cnt++;
    }
    
    if (info->fail_cnt > FTP_FAIL_CNT_MAX){
        info->func(FTP_RET_ERR);
        info->state = 0;
    }
}

int32_t w4g_ftp_connect(char_t *path, char_t *fname, uint8_t cmd, ftp_cb_func func){
    char_t fpath[50]={0};
    if (strlen(path) == 0){
        strncpy(fpath, fname, sizeof(fpath)); 
    }else{
        sprintf(fpath, "%s/%s", path, fname);
    }
    
    int32_t len = w4g_ftp_get_file_size(fpath);
    if (len == -1){
        printf("w4g_ftp_connect get file:%s fail\r\n", fpath);
        return -1;
    }
    
    g_ftpInfo.cmd = cmd; 
    g_ftpInfo.func = func;
    g_ftpInfo.file_len = len;
    g_ftpInfo.file_offset = 0;
    g_ftpInfo.pack_len = 0;
    g_ftpInfo.fail_cnt = 0;
    memcpy(g_ftpInfo.path, fpath, strlen(fpath)+1);
    g_ftpInfo.state = 1;
    printf("w4g_ftp_connect success\r\n");
    return 0;
}

static void poll_recv(void){
    uint8_t data;
    if(usart3_receive(&data)){
       //printf("%c",data);
       W4gRecv_Parse(data);
    }
}

static void poll_task(void *para){
    NetW4g_power_on();
    while(1){
        poll_recv();
        
        os_msleep(1);
    }
}

static void ftp_task(void *para){
    while(1){
        w4g_ftp_poll(&g_ftpInfo);
        os_msleep(50);
    }
}

int32_t w4g_get_csq(void){
    return g_w4g.csq;
}
int32_t w4g_init(char_t *ip, uint32_t port){
    int32_t ret = 0;
    g_w4g_mutex = os_mutex_create();
    
    os_pthread_t w4g_recv_thread;
    os_pthread_t w4g_ftp_thread;
    
    int32_t addr_val[4]={0};
    sscanf(ip, "%d.%d.%d.%d", &addr_val[0], &addr_val[1], &addr_val[2], &addr_val[3]);
    g_w4g.serveip[0] = addr_val[0];
    g_w4g.serveip[1] = addr_val[1];
    g_w4g.serveip[2] = addr_val[2];
    g_w4g.serveip[3] = addr_val[3];
    g_w4g.serveport = port;
    
    g_w4g.tcp_socket = 1;
    g_w4g.ftp_socket = 2;
    
    usart3_init(115200u);
    w4g_port_init();

    w4g_recv_queue = xQueueCreate(GPRS_RECV_DATA_LEN, sizeof(uint8_t));
    if (os_pthread_create("w4g_poll", &w4g_recv_thread, poll_task, NULL,  OS_TASK_PRIO_HIGHT, OS_STACK_SIZE_LARGE) != 0){
        ret = -1;
    }

    if (os_pthread_create("w4g_ftp", &w4g_ftp_thread, ftp_task, NULL,  OS_TASK_PRIO_BELOW_NORMAL, OS_STACK_SIZE_LARGE) != 0){
        ret = -1;
    }    
    
    return ret;
}

